#include "hal_sysclk.h"
#include <device.h>
#include <driverlib.h>

// 保存最近一次配置
static hal_sysclk_cfg_t s_last_cfg;
static uint32_t s_sysclk_freq = 0;
static uint32_t s_lspclk_freq = 0;

static uint32_t hal_sysctl_make_config(const hal_sysclk_cfg_t *cfg)
{
    uint32_t ti_cfg = 0;
    // 时钟源
    if (cfg->src == HAL_SYSCLK_SRC_XTAL) {
        ti_cfg |= SYSCTL_OSCSRC_XTAL;
    } else {
        ti_cfg |= SYSCTL_OSCSRC_OSC2;
    }
    // PLL相关
    if (cfg->pll_enable)
        ti_cfg |= SYSCTL_PLL_ENABLE;
    else
        ti_cfg |= SYSCTL_PLL_BYPASS;
    ti_cfg |= SYSCTL_IMULT(cfg->imult);
    ti_cfg |= SYSCTL_REFDIV(cfg->refdiv);
    ti_cfg |= SYSCTL_ODIV(cfg->odiv);
    ti_cfg |= SYSCTL_SYSDIV(cfg->sysdiv);
    ti_cfg |= SYSCTL_DCC_BASE_0;
    return ti_cfg;
}

bool hal_sysclk_init(void)
{
    // Set up PLL control and clock dividers
    //
    SysCtl_setClock(DEVICE_SETCLOCK_CFG);

    //
    // Make sure the LSPCLK divider is set to the default (divide by 4)
    //
    SysCtl_setLowSpeedClock(SYSCTL_LSPCLK_PRESCALE_4);

    //
    // These asserts will check that the #defines for the clock rates in
    // device.h match the actual rates that have been configured. If they do
    // not match, check that the calculations of DEVICE_SYSCLK_FREQ and
    // DEVICE_LSPCLK_FREQ are accurate. Some examples will not perform as
    // expected if these are not correct.
    //
    ASSERT(SysCtl_getClock(DEVICE_OSCSRC_FREQ) == DEVICE_SYSCLK_FREQ);
    ASSERT(SysCtl_getLowSpeedClock(DEVICE_OSCSRC_FREQ) == DEVICE_LSPCLK_FREQ);

    return true;
}

/*
bool hal_sysclk_init(const hal_sysclk_cfg_t *cfg)
{
    if (!cfg) return false;
    s_last_cfg = *cfg;

    uint32_t ti_cfg = hal_sysctl_make_config(cfg);
    if (!SysCtl_setClock(ti_cfg))
        return false;

    // 默认LSPCLK为4分频 default (divide by 4)
    SysCtl_setLowSpeedClock(SYSCTL_LSPCLK_PRESCALE_4);

    // 记录频率
    s_sysclk_freq = SysCtl_getClock(cfg->freq_in_hz);
    s_lspclk_freq = SysCtl_getLowSpeedClock(cfg->freq_in_hz);

    return true;
}
 */

uint32_t hal_sysclk_get_freq(void)
{
    return s_sysclk_freq ? s_sysclk_freq : DEVICE_SYSCLK_FREQ;
}

uint32_t hal_lspclk_get_freq(void)
{
    return s_lspclk_freq ? s_lspclk_freq : DEVICE_LSPCLK_FREQ;
}
